package com.zh.mycommon.util;

import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;

/**
 * @author Zhou
 * @date 19:07 2022/6/26
 */
public final class MyNetworkUtil {
    public static void main(String[] args) throws SocketException, UnknownHostException {
        String hostIp = getHostIp();
        String hostName = getHostName();
        System.out.println("hostIp = " + hostIp);
        System.out.println("hostName = " + hostName);
        System.out.println("mac address = " + getLocalMac());
    }

    /**
     * 测试IP网络是否连通
     *
     * @param ip ip
     * @return bool
     */
    public static boolean isReachable(String ip) {
        try {
            InetAddress address = InetAddress.getByName(ip);
            return address.isReachable(1000);
        } catch (Exception ex) {
            return false;
        }
    }

    /**
     * 返回本机名
     *
     * @return hostname
     */
    public static String getHostName() {
        try {
            InetAddress addr = InetAddress.getLocalHost();
            return addr.getHostName();
        } catch (UnknownHostException ex) {
            throw new RuntimeException("获取host异常");
        }
    }

    /**
     * 返回本机 InetAddress
     *
     * @return ip
     */
    public static InetAddress getInetAddress() {
        try {
//            // 优先查找公网 IP（非内网 IP）
//            InetAddress address = findAddress(false);
//
//            if (address == null) { //查找内网IP
//                address = findAddress(true);
//            }
//            if (address == null) { //直接返回LocalHost
//                address = InetAddress.getLocalHost();
//            }

            return InetAddress.getLocalHost();
        } catch (Exception e) {
            System.err.println("获取本机IP地址失败: " + e.getMessage());
            return null;
        }
    }

    /**
     * 返回本机IP
     *
     * @return ip
     */
    public static String getHostIp() {
        var address = getInetAddress();
        return address == null ? "127.0.0.1" : address.getHostAddress();
    }

    // 查找 IP 地址。是否只查找内网地址（true=只查内网，false=查非内网）
    private static InetAddress findAddress(boolean onlySiteLocal) throws SocketException {
        for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
            NetworkInterface intf = en.nextElement();
            var name = intf.getName().toLowerCase();  // 转换为小写

            // 跳过虚拟网卡（如 VMware、Docker、Loopback）
            if (name.contains("docker") || name.contains("lo") || name.contains("tun") || name.contains("vmnet")) {
                continue;
            }

            for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                InetAddress inetAddress = enumIpAddr.nextElement();
                // 只取 IPv4 地址，且非 loopback
                if (inetAddress instanceof java.net.Inet4Address && !inetAddress.isLoopbackAddress()) {
                    boolean isSiteLocal = inetAddress.isSiteLocalAddress();
                    // 根据 onlySiteLocal 决定返回哪种地址
                    if (onlySiteLocal == isSiteLocal) {
                        return inetAddress;
                    }
                }
            }
        }
        return null;
    }


    /**
     * 获得本机物理地址
     *
     * @return 本机物理地址
     * @since 5.7.3
     */
    public static String getLocalMac() {
        try {
            var mac = getHardwareAddress(InetAddress.getLocalHost());

            return asString(mac);
        } catch (IOException e) {
            System.err.println("获取本机Mac地址失败: " + e.getMessage());
            return "";
        }
    }

    private static String asString(byte[] hardwareAddress) {
        if (hardwareAddress == null || hardwareAddress.length == 0) {
            return "";
        }
        StringBuilder macAddress = new StringBuilder();
        for (int i = 0; i < hardwareAddress.length; i++) {
            macAddress.append(String.format("%02X", hardwareAddress[i]));
            if (i < hardwareAddress.length - 1) {
                macAddress.append(":");
            }
        }
        return macAddress.toString();
    }

    // 获得指定地址信息中的硬件地址
    public static byte[] getHardwareAddress(InetAddress inetAddress) throws SocketException {
        var networkInterface = NetworkInterface.getByInetAddress(inetAddress);
        return networkInterface.getHardwareAddress();
    }

}
